1 /* 2 * libdvbv5-d — a D binding to the libdvbv5 library. 3 * 4 * Copyright © 2018, 2019 Russel Winder 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 module libdvbv5_d.types; 21 22 import std.exception: enforce; 23 import std.string: toStringz; 24 25 import libdvbv5_d.dvb_demux: dvb_dmx_open, dvb_dmx_close; 26 import libdvbv5_d.dvb_fe: dvb_v5_fe_parms, dvb_fe_open, dvb_fe_close; 27 import libdvbv5_d.dvb_frontend: fe_delivery_system; 28 import libdvbv5_d.dvb_file: dvb_file, dvb_entry, dvb_file_free, dvb_file_formats, dvb_read_file_format; 29 import libdvbv5_d.dvb_scan: dvb_v5_descriptors, check_frontend_t, dvb_scan_transponder, dvb_scan_free_handler_table; 30 31 /** 32 * A pair (adapter_number, frontend_number) to uniquely identify the frontends 33 * available at any one time during execution. 34 */ 35 struct FrontendId { 36 const uint adapter_number; 37 const uint frontend_number; 38 39 this(const uint a_n, const uint f_n) { 40 adapter_number = a_n; 41 frontend_number = f_n; 42 } 43 } 44 45 /** 46 * A pair (where the first item is a `FrontendId` pair) to describe the tuning information 47 * for a given frontend when it is tuned in. 48 */ 49 struct TuningId { 50 const FrontendId frontend_id; 51 const string channel_name; 52 53 this(const FrontendId f_i, const string c_n) { 54 frontend_id = f_i; 55 channel_name = c_n; 56 } 57 } 58 59 // TODO Rethink use of enforce here; what is the right way of dealing with errors? 60 // Enforcing the returned pointer to be non-null is a very blunt tool. 61 62 /** 63 * An RAII compliant pointer to the kernel managed data relating to a frontend given a `FrontendId`. 64 * 65 * The idea is that this is a domain specific std::unique_ptr like type. 66 */ 67 struct FrontendParameters_Ptr { 68 private: 69 dvb_v5_fe_parms* ptr; 70 public: 71 @disable this(this); 72 this(const FrontendId fei, const uint verbose = 0, const uint useLegacyCall = 0) { 73 ptr = enforce(dvb_fe_open(fei.adapter_number, fei.frontend_number, verbose, useLegacyCall)); 74 } 75 ~this() { 76 if (ptr !is null) { 77 dvb_fe_close(ptr); 78 } 79 } 80 auto c_ptr() { return ptr; } 81 alias c_ptr this; 82 } 83 84 /** 85 * An RAII compliant pointer to a `dvb_file`. 86 */ 87 struct File_Ptr { 88 private: 89 dvb_file* ptr; 90 public: 91 @disable this(this); 92 this(const string path, const fe_delivery_system delsys = fe_delivery_system.SYS_UNDEFINED, const dvb_file_formats format = dvb_file_formats.FILE_DVBV5) { 93 ptr = enforce(dvb_read_file_format(toStringz(path), delsys, format)); 94 } 95 this(dvb_file* p) { ptr = p; } 96 ~this() { 97 if (ptr !is null) { 98 dvb_file_free(ptr); 99 } 100 } 101 bool isOpen() { return ptr !is null; } 102 auto c_ptr() { return ptr; } 103 alias c_ptr this; 104 }; 105 106 /** 107 * An RAII compliant DMX file descriptor. 108 */ 109 struct DMX_FD { 110 private: 111 const int fd; 112 public: 113 @disable this(this); 114 this(const FrontendId fei) { 115 fd = enforce(dvb_dmx_open(fei.adapter_number, fei.frontend_number)); 116 } 117 ~this() { dvb_dmx_close(fd); } 118 auto value() { return fd; } 119 }; 120 121 /** 122 * An RAII compliant pointer to a `dvb_v5_descriptors` object. 123 */ 124 struct ScanHandler_Ptr { 125 private: 126 dvb_v5_descriptors* ptr; 127 public: 128 @disable this(this); 129 this( 130 dvb_v5_fe_parms* frontendParameters, 131 dvb_entry* entry, 132 const int dmx_fd, 133 check_frontend_t check_frontend, 134 const uint other_nit, 135 const uint timeout_multiplier 136 ) { 137 ptr = enforce( 138 dvb_scan_transponder( 139 frontendParameters, 140 entry, 141 cast(int)dmx_fd, 142 check_frontend, 143 cast(void*)null, 144 cast(uint)other_nit, 145 cast(uint)timeout_multiplier 146 ) 147 ); 148 } 149 ~this() { 150 if (ptr !is null) { 151 dvb_scan_free_handler_table(ptr); 152 } 153 } 154 auto c_ptr() { return ptr; } 155 alias c_ptr this; 156 }; 157 158 unittest { 159 assert(FrontendId(0, 0) == FrontendId(0, 0)); 160 assert(FrontendId(0, 0) != FrontendId(1, 0)); 161 assert(FrontendId(0, 0) != FrontendId(0, 1)); 162 163 assert(TuningId(FrontendId(0, 0), "BBC NEWS") == TuningId(FrontendId(0, 0), "BBC NEWS")); 164 assert(TuningId(FrontendId(0, 0), "BBC NEWS") != TuningId(FrontendId(1, 0), "BBC NEWS")); 165 assert(TuningId(FrontendId(0, 0), "BBC NEWS") != TuningId(FrontendId(0, 1), "BBC NEWS")); 166 assert(TuningId(FrontendId(0, 0), "BBC NEWS") != TuningId(FrontendId(0, 0), "ITV")); 167 }